/**
	Copyright (c) 2009 Ozazo Pvt Ltd, INDIA

	Permission is hereby granted, free of charge, to any person or organization 
	obtaining a copy of this software and associated  documentation  files (the 
	"Software"), to deal in the Software without restriction, including without 
	limitation the rights to use, copy, modify, merge, publish, distribute, sub
	license, and/or sell copies of the Software, and to permit persons  to whom 
	the Software is furnished to do so, subject to the following conditions:
	
	The above copyright notice and  this permission notice shall be included in 
	all copies or substantial portions of the Software.
	
	THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING  BUT NOT  LIMITED  TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR  COPYRIGHT  HOLDERS  BE  LIABLE  FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY,  WHETHER  IN  AN  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
	FROM,  OUT  OF  OR  IN  CONNECTION  WITH  THE  SOFTWARE OR THE USE OR OTHER 
	DEALINGS IN THE SOFTWARE.
 */

package com.ozazo.wave.robots.fw.utils;

/**
 */

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

import com.ozazo.wave.robots.fw.config.ContainerConfig;
import com.ozazo.wave.robots.fw.config.DebugConfig;
import com.ozazo.wave.robots.fw.config.EngineConfig;
import com.ozazo.wave.robots.fw.config.ParserConfig;
import com.ozazo.wave.robots.fw.config.RobotConfig;
import com.ozazo.wave.robots.fw.config.RobotDetails;
import com.ozazo.wave.robots.fw.search.OpenSearchItem;
import com.ozazo.wave.robots.fw.search.OpenSearchResult;


/**
 * Sax Parser to parse the Wiki Result XML file.
 *
 * @author:   Araf Karsh Hamid
 * @version:  1.0
 * @serial:   20091121102030
 */

public final class RobotConfigSAXParser extends DefaultHandler{

	// To Hold the data while parsing the XML
	private String dataValue;
	
	// Config object variables
	private String name;
	private String className;
	private String profileName;
	private String iconName;
	private String attribute;

	private boolean isEnabled;
	
	private RobotConfig robotConfig;
	private ContainerConfig container;

	private String text;

	
	public RobotConfigSAXParser(){
	}

	/**
	 * Parse the XML directly from a file
	 *
	 * @param String
	 * @return RobotConfig
	 * @throws Exception
	 */
	
	public RobotConfig parse(String _fileName) throws Exception {
		if(_fileName == null) {
			throw new Exception("Invalid xml file=["+_fileName+"]");
		}
		return parseDocument(_fileName);
	}

	/**
	 * Parse the XML directly from a Stream
	 *
	 * @param Reader 
	 * @returns RobotConfig
	 */

	public RobotConfig parse(final Reader _reader) throws Exception {
		return parseDocument(new InputSource(_reader));
	}

	/**
	 * Actual Parsing is handled by this method
	 */

	private RobotConfig parseDocument(final InputSource _socketSource) throws Exception {
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			SAXParser sp = spf.newSAXParser();	// Get new parser instance
			sp.parse(_socketSource, this);		// Parse the XML
		}catch(SAXException se) {
			throw new Exception("SAX Exception", se);
		}catch(ParserConfigurationException pce) {
			throw new Exception("Parsing Exception", pce);
		}catch (IOException ie) {
			throw new Exception("File I/O Exception", ie);
		}
		return robotConfig;
	}

	/**
	 * Actual Parsing is handled by this method
	 */

	private RobotConfig parseDocument(final String _fileName) throws Exception {
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			SAXParser sp = spf.newSAXParser();	// Get new parser instance
			sp.parse(_fileName, this);		// Parse the XML
		}catch(SAXException se) {
			throw new Exception("SAX Exception", se);
		}catch(ParserConfigurationException pce) {
			throw new Exception("Parsing Exception", pce);
		}catch (IOException ie) {
			throw new Exception("File I/O Exception", ie);
		}
		return robotConfig;
	}

	/**
	 * Callback method call to read the Start element of the XML
	 */

	public void startElement(String uri, String localName, String qName, Attributes attributes) 
			throws SAXException { 
		//reset
		dataValue = null;
		if(qName.equalsIgnoreCase("RobotConfig")) {
			attribute = attributes.getValue("version");
			robotConfig = new RobotConfig(attribute);
		} else if (qName.equalsIgnoreCase("ContainerConfig")) {
			attribute = attributes.getValue("isEnabled");
			if(attribute != null) {
				isEnabled = (attribute.trim().equalsIgnoreCase("Yes") || attribute.trim().equalsIgnoreCase("True")) ? true : false;
			}			
			container = new ContainerConfig(isEnabled);
		} else if (qName.equalsIgnoreCase("debug")) {
			attribute = attributes.getValue("isEnabled");	
			if(attribute != null) {
				isEnabled = (attribute.trim().equalsIgnoreCase("Yes") || attribute.trim().equalsIgnoreCase("True")) ? true : false;
			}
		} else if(qName.equalsIgnoreCase("Engine")) {
			attribute = attributes.getValue("isEnabled");			
			if(attribute != null) {
				isEnabled = (attribute.trim().equalsIgnoreCase("Yes") || attribute.trim().equalsIgnoreCase("True")) ? true : false;
			}
		}
	}
	
	/**
	 * Read the values from the stream
	 */

	public void characters(char[] ch, int start, int length) throws SAXException {
		dataValue = new String(ch,start,length);
	}
	
	/**
	 * Process the value data
	 */

	public void endElement(String uri, String localName, String qName) throws SAXException {

		if(qName.equalsIgnoreCase("debug")) {
			container.setDebugConfig(new DebugConfig(isEnabled, dataValue));
		} else if(qName.equalsIgnoreCase("robotName")) {
			name = dataValue;
		} else if(qName.equalsIgnoreCase("robotProfile")) {
			profileName = dataValue;			
		} else if(qName.equalsIgnoreCase("robotIcon")) {
			iconName = dataValue;			
		} else if(qName.equalsIgnoreCase("RobotDetails")) {
			container.setRobotDetails(new RobotDetails(name, profileName, iconName));
		} else if(qName.equalsIgnoreCase("componentName")) {
			name = dataValue;			
		} else if(qName.equalsIgnoreCase("className")) {
			className = dataValue;					
		} else if(qName.equalsIgnoreCase("Parser")) {
			container.setParserConfig(new ParserConfig(name, className));
			name = null;
			className = null;
		} else if(qName.equalsIgnoreCase("Engine")) {
			container.addEngineConfig(new EngineConfig(isEnabled, name, className));
			name = null;
			className = null;
		} else if(qName.equalsIgnoreCase("ContainerConfig")) {
			robotConfig.addContainer(container);
		}
		attribute = null;
		dataValue = null;
	}

	/**
	 * ----------------------------------------------------------------------------
	 * Test the Parser
	 * ----------------------------------------------------------------------------
	 */
	
	public static void main(String[] args) throws Exception {
		RobotConfigSAXParser parser = new RobotConfigSAXParser();

		RobotConfig robot = parser.parse(args[0]);
		System.out.println(robot.toXMLString());
	}
}